//
//  GameViewController.m
//  iOSPractice
//
//  Created by hoolai on 2018/11/27.
//  Copyright © 2018年 hoolai. All rights reserved.
//

#import "GameViewController.h"


@interface GameViewController ()<WinViewDelegate,LoseViewDelegate>
@property (nonatomic, strong) NSArray *itemsArray;
@property (nonatomic, strong) CMMotionManager *motionManager;
@property (nonatomic, strong) UIImageView *playerView;
@property (nonatomic, assign) double moveX,moveY;
@property (nonatomic, strong) CADisplayLink *gameTimer;


@end

@implementation GameViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    CMMotionManager *manager = [[CMMotionManager alloc] init];
    self.motionManager = manager;
    if(![self.motionManager isAccelerometerActive]){
        [self.motionManager startAccelerometerUpdates];
    }
    //[self loadMap];
    
    
   
    

    
    
    
}

- (void)viewDidAppear:(BOOL)animated{
    [self loadMap];
    [self useAccelerometerPush];
}

- (NSArray *)itemsArray{
    //用_itemsArray的理由： 本身这里就是重写get方法，如果用self. 的方式调用会导致无限递归
    if(_itemsArray == nil){
        NSString *path = [[NSBundle mainBundle]pathForResource:@"maps" ofType:@"plist"];
        NSArray *arr = [NSArray arrayWithContentsOfFile:path];
        NSMutableArray *tempArr = [NSMutableArray array];
        for (NSDictionary *dict in arr) {
            GameItems *items = [GameItems itemsWithDict:dict];
            [tempArr addObject:items];
        }
        _itemsArray = tempArr;
    }
    return _itemsArray;
}

- (void)loadMap{
    //清空视图内的所有子视图
    for (UIView *view in self.view.subviews) {
        [view removeFromSuperview];
    }
    //获取到本关内的地图项
    GameItems *items = self.itemsArray[self.level - 1];
    //必须先加障碍物 规则与碰撞判定有关
    for (NSString *barrier in items.barriers){
        NSArray *arr = [barrier componentsSeparatedByString:@","];
        int x = [arr[0] intValue];
        int y = [arr[1] intValue];
        [self createImage:@"barrier" X:x Y:y Type:BARRIER];
        //NSLog(@"barrier : %i,%i",x,y);
    }
    for (NSString *trap in items.traps) {
        NSArray *arr = [trap componentsSeparatedByString:@","];
        int x = [arr[0] intValue];
        int y = [arr[1] intValue];
        [self createImage:@"trap" X:x Y:y Type:TRAP];
        //NSLog(@"trap : %i,%i",x,y);
    }
    {
        NSArray *arr = [items.goal componentsSeparatedByString:@","];
        int x = [arr[0] intValue];
        int y = [arr[1] intValue];
        [self createImage:@"goal" X:x Y:y Type:GOAL];
        //NSLog(@"goal : %i,%i",x,y);
    }
    self.playerView = [[UIImageView alloc] init];
    [self.playerView setImage:[UIImage imageNamed:[AppSettings shareSettings].myBeast.icon]];
    [self.playerView setFrame:CGRectMake(195, 100, 40, 40)];
    [self.view addSubview:self.playerView];
    self.playerView.tag = PLAYER;
    //[self createImage:[AppSettings shareSettings].myBeast.icon X:195 Y:100 Type:PLAYER];
}

- (void)createImage:(NSString *)name X:(int)x Y:(int)y Type:(ItemType)type{
    //默认大小都为40x40
    UIImageView *imageview = [[UIImageView alloc] init];
    [imageview setImage:[UIImage imageNamed:name]];
    [imageview setFrame:CGRectMake(x, y, 40, 40)];
    [self.view addSubview:imageview];
    imageview.tag = type;
}

//隐藏状态栏
- (BOOL)preferStatusBarHidden{
    return YES;
}

//初始化加速度计
- (void)useAccelerometerPush{
    //初始化全局管理对象
    
    //判断加速度计可不可用，判断加速度计是否开启
    if (![self.motionManager isAccelerometerAvailable]){
        NSLog(@"a");
    }
    
    if(![self.motionManager isAccelerometerActive]){
        NSLog(@"b");
    }
    //__block double x,y;
    if ([self.motionManager isAccelerometerAvailable] && [self.motionManager isAccelerometerActive]){
        NSLog(@"启动");
        //告诉manager，更新频率是100Hz
        self.motionManager.accelerometerUpdateInterval = 0.01;
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        //Push方式获取和处理数据
        [self.motionManager startAccelerometerUpdatesToQueue:queue                                      withHandler:^(CMAccelerometerData *accelerometerData, NSError *error)
         {
             self.moveX = accelerometerData.acceleration.x *10;
             self.moveY = - accelerometerData.acceleration.y *10;
             //x = accelerometerData.acceleration.x;
             //y = accelerometerData.acceleration.y;
             //[self moveX:accelerometerData.acceleration.x Y:accelerometerData.acceleration.y];
             //NSLog(@"X = %.04f",accelerometerData.acceleration.x);
             //NSLog(@"Y = %.04f",accelerometerData.acceleration.y);
             //NSLog(@"Z = %.04f",accelerometerData.acceleration.z);
         }];
    }
    else {
        NSLog(@"启动失败");
    }
    
    //CADisplayLink *gameTimer;
    self.gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(move)];
    
    //[gameTimer performSelectorOnMainThread:@selector(move:) withObject:[NSArray arrayWithObjects:[NSNumber numberWithDouble:x],[NSNumber numberWithDouble:y],nil] waitUntilDone:YES];
    [self.gameTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)move{
    double mx = self.moveX,my = self.moveY;
    //因为是多线程操作，考虑到可能会运行时 self.moveX 的值受到改变 所以在这个方法内部统一一下
    CGAffineTransform trans = self.playerView.transform;
    CGRect frame = self.playerView.frame;
    
    CGFloat playerX = frame.origin.x;
    CGFloat playerY = frame.origin.y;
    CGFloat playerW = frame.size.width;
    CGFloat playerH = frame.size.height;
    
    
    
    CGRect newframe = CGRectMake(playerX + mx, playerY + my, playerW, playerH);
    BOOL moveable = YES;
    for (UIView *view in self.view.subviews) {
        if(view == self.playerView) continue;
        if(CGRectIntersectsRect(newframe, view.frame)){//判断两个frame是否有交叉部分
            if(view.tag == BARRIER){
                CGVector vector = [self collisionDetection1:view.frame player:frame X:mx Y:my];//碰撞检测模式1
                //CGVector vector = [self collisionDetection2:view.frame player:frame X:mx Y:my];//碰撞检测模式2
                mx = vector.dx;
                my = vector.dy;
                
            }
            else if(view.tag == GOAL){
                //NSLog(@"通关");
                return [self win];//游戏结束应直接跳出 防止判定冲突
                
            }
            else if(view.tag == TRAP){
                //NSLog(@"你死了");
                return [self lose];
            }
        }
        //超出边界
//        if(playerX + mx < 0){
//            moveable = NO;
//            playerX = 0;
//            self.playerView.frame = CGRectMake(playerX, playerY, playerW, playerH);
//        }else if(playerX +playerW + mx > [UIScreen mainScreen].bounds.size.width){
//            moveable = NO;
//            playerX = [UIScreen mainScreen].bounds.size.width - playerW;
//            self.playerView.frame = CGRectMake(playerX, playerY, playerW, playerH);
//        }
//
//        if(playerY + my < 0){
//            moveable = NO;
//            playerY = 0;
//            self.playerView.frame = CGRectMake(playerX, playerY, playerW, playerH);
//        }else if(playerY + playerH + my > [UIScreen mainScreen].bounds.size.height){
//            moveable = NO;
//            playerY = [UIScreen mainScreen].bounds.size.height - playerH;
//            self.playerView.frame = CGRectMake(playerX, playerY, playerW, playerH);
//        }
        if(playerX + mx < 0){
            mx = -playerX ;
        }else if(playerX +playerW + mx > [UIScreen mainScreen].bounds.size.width){
            mx = [UIScreen mainScreen].bounds.size.width - playerX - playerW;
        }
        if(playerY + my < 0){
            my = -playerY;
        }else if(playerY + playerH + my > [UIScreen mainScreen].bounds.size.height){
            my = [UIScreen mainScreen].bounds.size.height - playerY - playerH;
        }
    }
    if(moveable){
        self.playerView.transform = CGAffineTransformTranslate(trans, mx, my);
        //NSLog(@"moved");
    }
}

//碰撞检测的效果不太好 所以写了几种来测试效果
//碰撞检测1 原理：碰撞后挤出
- (CGVector)collisionDetection1:(CGRect)barrierFrame player:(CGRect)playerFrame X:(double)mx Y:(double)my{
    int range = 10; //barrier的判断范围 一般为mv的最大值
    
    //CGRect barrierFrame = frame;
    CGFloat barrierX = barrierFrame.origin.x;
    CGFloat barrierY = barrierFrame.origin.y;
    CGFloat barrierW = barrierFrame.size.width;
    CGFloat barrierH = barrierFrame.size.height;
    
    CGFloat playerX = playerFrame.origin.x;
    CGFloat playerY = playerFrame.origin.y;
    CGFloat playerW = playerFrame.size.width;
    CGFloat playerH = playerFrame.size.height;
    //已经有交叉部分了 判断是从什么方向碰撞的 直接挤出位置即可
    //相对中心位置挤出
    //*表示barrier的边缘 @表示barrier的中心 p代表player位置
    /*
     *****      *****
     * @ p  ➡️  * @ *p
     *****      *****
     */
    if(playerX + mx > barrierX + barrierW - range){
        mx = barrierX + barrierW - playerX;
    }
    /*
     *****      *****
     p @ *  ➡️ p* @ *
     *****      *****
     */
    else if(playerX + mx + playerW < barrierX + range){//
        mx = barrierX -playerX - playerW;
    }
    
    /*
     p
     **p**      *****
     * @ *  ➡️  * @ *
     *****      *****
     */
    //对于斜角方向的判断会有冲突  重新判断一次交叉
    
    if(playerY + my + playerH < barrierY + range){
        my = barrierY - playerH -playerY;
    }
    /*
     *****      *****
     * @ *  ➡️  * @ *
     **p**      *****
     p
     */
    else if(playerY + my >  barrierY + barrierH - range){
        my = barrierY + barrierH - playerY;
    }
    //对于多个连续barrier 移动的时候有bug
    //试想的解决方法：先判断上下 和 左右两个方向哪个进入更多一点
    //我懒得改了（心态崩了）
    return CGVectorMake(mx, my);
}

//碰撞检测2 原理：即将碰撞时预防
//显示效果类似于 吸附
//事实证明两种碰撞检测没有任何区别 除了碰撞2会导致更多的死亡判定以外
// *这是一个失败的碰撞检测（摔）
- (CGVector)collisionDetection2:(CGRect)barrierFrame player:(CGRect)playerFrame X:(double)mx Y:(double)my{
    
    CGFloat barrierX = barrierFrame.origin.x;
    CGFloat barrierY = barrierFrame.origin.y;
    CGFloat barrierW = barrierFrame.size.width;
    CGFloat barrierH = barrierFrame.size.height;
    
    CGFloat playerX = playerFrame.origin.x;
    CGFloat playerY = playerFrame.origin.y;
    CGFloat playerW = playerFrame.size.width;
    CGFloat playerH = playerFrame.size.height;
    
    if(playerX + playerW/2 >= barrierX + barrierW){
        mx = barrierW + barrierX - playerX;
    }else if(playerX + playerW/2 <= barrierX){
        mx = barrierX - playerX - playerW;
    }
    if(playerY + playerH/2 >= barrierY + barrierH){
        my = barrierH + barrierY - playerY;
    }
    else if(playerY + playerH/2 <= barrierY){
        my = barrierY - playerY - playerH;
    }
    return CGVectorMake(mx, my);
}

- (void)win{
    [self.gameTimer setPaused:YES];
    if(self.level != [AppSettings maxLevel]){
        if([AppSettings shareSettings].level == self.level){
            [AppSettings shareSettings].level = ++self.level;
            
            NSString *path = [[AppSettings dataFilePath]stringByAppendingString:@"/user.plist"];
            if([[NSFileManager defaultManager]fileExistsAtPath:path]){
                NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
                [dict setValue:[NSNumber numberWithInteger:self.level] forKey:@"level"];
                [dict writeToFile:path atomically:YES];
            }
            NSLog(@"level up");
        }
        else{
            ++self.level;
            NSLog(@"level up2");
        }
        
    }else {
        NSLog(@"已全部通关");
    }
    
    WinView *winView = [[[NSBundle mainBundle]loadNibNamed:@"win" owner:self options:nil] lastObject];
    winView.delegate = self;
    [self.view addSubview:winView];

}

- (void)goToNextLevel{
    [self loadMap];
    [self.gameTimer setPaused:NO];
    
}

- (void)goBackToMenu{
    [self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
}

- (void)lose{
    [self.gameTimer setPaused:YES];
    LoseView *loseView = [[[NSBundle mainBundle]loadNibNamed:@"lose" owner:self options:nil] lastObject];
    loseView.delegate = self;
    [self.view addSubview:loseView];
}

- (void)retry{
    [self loadMap];
    [self.gameTimer setPaused:NO];
}
@end
